#ifndef MESH_SPECIFICS_H

//--------------------------------------------------------
//		DEFINITIONS
//--------------------------------------------------------
#define MESH_SPECIFICS_H

//--------------------------------------------------------
//		INCLUDES
//--------------------------------------------------------
#include <OpenMesh/Core/Geometry/VectorT.hh>
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/IO/Options.hh>
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
#include <vector>
using namespace OpenMesh;

// Include "previous edge" in half edge data structure
struct MyTraits : public OpenMesh::DefaultTraits
{
	HalfedgeAttributes( OpenMesh::Attributes::PrevHalfedge );
	VertexAttributes( OpenMesh::Attributes::Color );
	FaceAttributes( OpenMesh::Attributes::Color );	

	// Let Point and Normal be a vector of doubles
	typedef OpenMesh::Vec3d Point;
	typedef OpenMesh::Vec3d Normal;
	typedef OpenMesh::Vec4f Color;

	// store importance of a vertex
	// 0 = not important
	// 1 = important
	VertexTraits
	{
	private:
		int  importance_; 
		double weight_;
		int  index;
		int edge1;
		int edge2;
		Point oldpt;
		int type;
		Vec4f oldColor;

	public:
		VertexT() : importance_( 0 ), weight_( 0 ), index(0),edge1(-1), edge2(-1){ }
	
		const int& importance() const { return importance_; }
		void set_importance(const int& i) { importance_ = i; }

		const double& weight() const { return weight_; }
		void set_weight(const double& d) { weight_ = d; }

		const int& get_index() { return index; }
		void set_index(const int& i) { index = i; }

		const int& left_edge_index() { return edge1; }
		void left_edge_index(const int& i) { edge1 = i; }

		const int& right_edge_index() { return edge2; }
		void right_edge_index(const int& i) { edge2 = i; }

		const int& getType() { return type; }
		void setType(const int& i) { type = i; }

		const Point& getPoint() { return oldpt; }
		void setPoint(const Point& p) { oldpt = p; }

		const Vec4f& getColor() const { return oldColor; }
		void setColor(const Vec4f& c) { oldColor=c; }
	};

	// store importance of an edge
	// 0 = not important
	// 1 = important
	EdgeTraits
	{
	private:
		//using importance for sharp edges...
		int  importance_;
		bool sharp;
		Vec4f color;
	public:

		EdgeT() : importance_( 0 ), sharp(false) { }
	
		const int& importance() const { return importance_; }
		void set_importance(const int& i) { importance_ = i; }
		const bool& sharpness() const { return sharp; }
		void set_sharp(const bool& b) { sharp = b; }
		const Vec4f& getColor() const { return color; }
		void setColor(const Vec4f& c) { color=c; }
	};

	// store importance of a face
	// 0 = not important
	// 1 = important
	FaceTraits
	{
	private:

		int  importance_;
		std::vector< int > indices;
		int  index;
	public:

		FaceT() : importance_( 0 ) {  indices.clear(); }
	
		const int& importance() const { return importance_; }
		void set_importance(const int& i) { importance_ = i; }

		const std::vector<int>& get_indices() const { return indices; }
		void set_indices( std::vector<int>& v ) { indices = v; }

		const int& getIndex() const { return index; }
		void setIndex(const int& i) { index = i; }
	};

};
typedef PolyMesh_ArrayKernelT<MyTraits> PolyMesh;


// Property to add to every mesh containing extra data we define
struct MeshData
{
  bool          isVisible;

  MeshData()
    : isVisible(false)
  { }

  MeshData( const MeshData& _cpy )
    : isVisible(_cpy.isVisible)
  { }


  // ---------- assignment

  MeshData& operator = (const MeshData& _rhs) 
  { 
    isVisible = _rhs.isVisible;
    return *this;
  }

  MeshData& operator = (bool _rhs) { isVisible = _rhs; return *this; }

  // ---------- comparison

  bool operator == (const MeshData& _rhs) const
  { 
    return isVisible == _rhs.isVisible;
  }

  bool operator != (const MeshData & _rhs) const { return !(*this == _rhs); }

};

typedef OpenMesh::MPropHandleT<MeshData> mData;

#endif